package com.jiang.daily.Q3305;

/**
 * @author Jiang
 * @version 1.0
 * @date 2025/03/12 21:29
 */
class Solution {
    public int countOfSubstrings(String word, int k) {
        /// count(k) 表示子字符串包含至少 k 个辅音字母且每个元音字母至少出现一次的子字符串的总数
        /// count(k + 1) 表示子字符串包含至少 k+1 个辅音字母且每个元音字母至少出现一次的子字符串的总数

        /// 因此。count(k) - count(k + 1) 代表了那些符合以下条件的子字符串的数量
        /// 1. 子字符串包含至少 k 个辅音字母
        /// 2. 子字符串不包含至少 k+1 个辅音字母
        /// 即：包含至少 k 个辅音字母、但又不包含更多的子字符串的数量
        return count(word, k) - count(word, k + 1);
    }

    /**
     * 统计字符串 word 中元音字母（'a'、'e'、'i'、'o'、'u'）至少 出现一次，且至少包含 k 个辅音字母的子字符串的总数
     */
    private int count(String word, int k) {
        int length = word.length();
        int counter = 0;
        int[] letters = new int[26];
        int vowelCount = 0;
        int consonantCount = 0;

        int start = 0;
        for (int end = 0; end < length; end++) {
            char ch = word.charAt(end);
            if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
                if (letters[ch - 'a'] == 0) {
                    vowelCount += 1;
                }
                letters[ch - 'a'] += 1;
            } else {
                consonantCount += 1;
            }

            while (vowelCount == 5 && consonantCount >= k) {
                // 辅音字母大于等于 k 个，且元音字母至少 1 个的子字符串个数
                counter += length - end;

                // 右移窗口
                char startChar = word.charAt(start);
                if (startChar == 'a' || startChar == 'e' || startChar == 'i' || startChar == 'o' || startChar == 'u') {
                    // 如果最左侧的字符为元音字母，则回退 1 个元音字母的数据
                    letters[startChar - 'a'] -= 1;
                    if (letters[startChar - 'a'] == 0) {
                        vowelCount -= 1;
                    }
                } else {
                    // 如果最左侧的字符为辅音字母，则回退 1 个辅音字母的数据
                    consonantCount -= 1;
                }
                // 右移窗口完成，则最左侧字母指向下一个字母
                start += 1;
            }

        }

        return counter;
    }
}
